<!DOCTYPE html>



  


<html class="theme-next muse use-motion" lang="zh-CN">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/blog/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/blog/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/blog/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/blog/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/blog/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/blog/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/blog/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Hexo, NexT">










<meta name="description" content="SpringBoot Jar包启动原理JAR的概念 在软件领域，JAR文件（Java归档，英语：Java Archive）是一种软件包文件格式，通常用于聚合大量的Java类文件、相关的元数据和资源（文本、图片等）文件到一个文件，以便开发Java平台应用软件或库。  可执行JAR包一个JAR包能否执行就是看能否通过java -jar命令来直接运行程序。在平常的编码过程中，我们会大量的用到第三方的JA">
<meta property="og:type" content="article">
<meta property="og:title" content="SpringBoot启动原理">
<meta property="og:url" content="https://arrycoder.gitee.io/Spring/SpringBoot-1/index.html">
<meta property="og:site_name" content="arry&#39;s blog">
<meta property="og:description" content="SpringBoot Jar包启动原理JAR的概念 在软件领域，JAR文件（Java归档，英语：Java Archive）是一种软件包文件格式，通常用于聚合大量的Java类文件、相关的元数据和资源（文本、图片等）文件到一个文件，以便开发Java平台应用软件或库。  可执行JAR包一个JAR包能否执行就是看能否通过java -jar命令来直接运行程序。在平常的编码过程中，我们会大量的用到第三方的JA">
<meta property="og:locale" content="zh-CN">
<meta property="og:updated_time" content="2020-01-07T07:29:05.250Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="SpringBoot启动原理">
<meta name="twitter:description" content="SpringBoot Jar包启动原理JAR的概念 在软件领域，JAR文件（Java归档，英语：Java Archive）是一种软件包文件格式，通常用于聚合大量的Java类文件、相关的元数据和资源（文本、图片等）文件到一个文件，以便开发Java平台应用软件或库。  可执行JAR包一个JAR包能否执行就是看能否通过java -jar命令来直接运行程序。在平常的编码过程中，我们会大量的用到第三方的JA">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/blog/',
    scheme: 'Muse',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: 'Author'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://arrycoder.gitee.io/Spring/SpringBoot-1/">





  <title>SpringBoot启动原理 | arry's blog</title>
  





  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?97f9adfda8d04eb91dd054a98264d191";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>




</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-CN">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/blog/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">arry's blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/blog/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            Home
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/blog/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
            
            Tags
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/blog/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            Categories
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/blog/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            Archives
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://arrycoder.gitee.io/blog/Spring/SpringBoot-1/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="arry">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/blog/uploads/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="arry's blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">SpringBoot启动原理</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2019-12-25T11:02:43+08:00">
                2019-12-25
              </time>
            

            

            
          </span>

          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h2 id="SpringBoot-Jar包启动原理"><a href="#SpringBoot-Jar包启动原理" class="headerlink" title="SpringBoot Jar包启动原理"></a>SpringBoot Jar包启动原理</h2><h3 id="JAR的概念"><a href="#JAR的概念" class="headerlink" title="JAR的概念"></a>JAR的概念</h3><blockquote>
<p>在软件领域，JAR文件（Java归档，英语：Java Archive）是一种软件包文件格式，通常用于聚合大量的Java类文件、相关的元数据和资源（文本、图片等）文件到一个文件，以便开发Java平台应用软件或库。</p>
</blockquote>
<h3 id="可执行JAR包"><a href="#可执行JAR包" class="headerlink" title="可执行JAR包"></a>可执行JAR包</h3><p>一个JAR包能否执行就是看能否通过java -jar命令来直接运行程序。在平常的编码过程中，我们会大量的用到第三方的JAR包，比如FastJSON，Spring等等，这种包通常大部分无法直接运行。还有一种JAR包，可以直接通过上面的命令直接运行起来，这种我们称为<strong>可执行jar包</strong>。那虚拟机如何知道一个JAR包是否是可运行的，答案都在MANIFEST.MF文件里。</p>
<p>当我们打完jar包之后，会在根目录下创建一个META-INF目录，里面包含着一个MANIFEST.MF文件。MANIFEST文件里包含了这个jar包的元信息，也因为这个文件，JAR包就可以实现普通ZIP包所不能实现的很多功能，包括电子签名，版本控制，包装密封，安全性等。以下是官网对该文件的<a href="https://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html" target="_blank" rel="noopener">简介</a>。</p>
<blockquote>
<p>JAR files support a wide range of functionality, including electronic signing, version control, package sealing, and others. What gives a JAR file this versatility? The answer is the JAR file’s <em>manifest</em>.</p>
<p>The manifest is a special file that can contain information about the files packaged in a JAR file. By tailoring this “meta” information that the manifest contains, you enable the JAR file to serve a variety of purposes.</p>
</blockquote>
<p>在可执行的JAR包中会指定<strong>MAIN-CLASS</strong>，作为JAR包启动的入口。</p>
<h3 id="FatJar"><a href="#FatJar" class="headerlink" title="FatJar"></a>FatJar</h3><p>普通的打包方式，会将所有类都掺杂在一起，而SpringBoot使用了FatJar将第三方的类放到lib目录下。项目所有的class都在BOOT-INF的classes目录下。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><span class="line">├── BOOT-INF</span><br><span class="line">│   ├── classes</span><br><span class="line">│   │   ├── META-INF</span><br><span class="line">│   │   ├── application.properties</span><br><span class="line">│   │   └── com</span><br><span class="line">│   └── lib</span><br><span class="line">│       ├── classmate-1.5.1.jar</span><br><span class="line">│       ├── hibernate-validator-6.0.18.Final.jar</span><br><span class="line">│       ├── jackson-annotations-2.10.1.jar</span><br><span class="line">│       ├── jackson-core-2.10.1.jar</span><br><span class="line">│       ├── jackson-databind-2.10.1.jar</span><br><span class="line">│       ├── jackson-datatype-jdk8-2.10.1.jar</span><br><span class="line">│       ├── jackson-datatype-jsr310-2.10.1.jar</span><br><span class="line">│       ├── jackson-module-parameter-names-2.10.1.jar</span><br><span class="line">│       ├── jakarta.annotation-api-1.3.5.jar</span><br><span class="line">│       ├── jakarta.validation-api-2.0.1.jar</span><br><span class="line">│       ├── jboss-logging-3.4.1.Final.jar</span><br><span class="line">│       ├── jul-to-slf4j-1.7.29.jar</span><br><span class="line">│       ├── log4j-api-2.12.1.jar</span><br><span class="line">│       ├── log4j-to-slf4j-2.12.1.jar</span><br><span class="line">│       ├── logback-classic-1.2.3.jar</span><br><span class="line">│       ├── logback-core-1.2.3.jar</span><br><span class="line">│       ├── slf4j-api-1.7.29.jar</span><br><span class="line">│       ├── snakeyaml-1.25.jar</span><br><span class="line">│       ├── spring-aop-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-beans-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-autoconfigure-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-starter-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-starter-json-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-starter-logging-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-starter-tomcat-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-starter-validation-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-boot-starter-web-2.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-context-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-core-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-expression-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-jcl-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-web-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── spring-webmvc-5.2.2.RELEASE.jar</span><br><span class="line">│       ├── tomcat-embed-core-9.0.29.jar</span><br><span class="line">│       ├── tomcat-embed-el-9.0.29.jar</span><br><span class="line">│       └── tomcat-embed-websocket-9.0.29.jar</span><br><span class="line">├── META-INF</span><br><span class="line">│   ├── MANIFEST.MF</span><br><span class="line">│   └── maven</span><br><span class="line">│       └── com.arry</span><br><span class="line">└── org</span><br><span class="line">    └── springframework</span><br><span class="line">        └── boot</span><br></pre></td></tr></table></figure>

<h3 id="自定义的ClassLoader"><a href="#自定义的ClassLoader" class="headerlink" title="自定义的ClassLoader"></a>自定义的ClassLoader</h3><p>因为改变了JAR包的结构，所以需要自定义ClassLoader来加载第三方包里的类。通过Manifest文件可以看出来，SpringBoot的jar包启动入口在JarLauncher。在launch方法里创建了<strong>LaunchedURLClassLoader</strong>。加载完类之后新建MethodRunner通过反射调用Start-Class的main方法。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">Manifest-Version: 1.0</span><br><span class="line">Implementation-Title: demo</span><br><span class="line">Implementation-Version: 0.0.1-SNAPSHOT</span><br><span class="line">Start-Class: com.arry.demo.DemoApplication</span><br><span class="line">Spring-Boot-Classes: BOOT-INF/classes/</span><br><span class="line">Spring-Boot-Lib: BOOT-INF/lib/</span><br><span class="line">Build-Jdk-Spec: 1.8</span><br><span class="line">Spring-Boot-Version: 2.2.2.RELEASE</span><br><span class="line">Created-By: Maven Archiver 3.4.0</span><br><span class="line">Main-Class: org.springframework.boot.loader.JarLauncher</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">package</span> org.springframework.boot.loader;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.loader.archive.Archive;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.loader.archive.Archive.Entry;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">JarLauncher</span> <span class="keyword">extends</span> <span class="title">ExecutableArchiveLauncher</span> </span>&#123;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> String BOOT_INF_CLASSES = <span class="string">"BOOT-INF/classes/"</span>;</span><br><span class="line">    <span class="keyword">static</span> <span class="keyword">final</span> String BOOT_INF_LIB = <span class="string">"BOOT-INF/lib/"</span>;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">JarLauncher</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="title">JarLauncher</span><span class="params">(Archive archive)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(archive);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">protected</span> <span class="keyword">boolean</span> <span class="title">isNestedArchive</span><span class="params">(Entry entry)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">return</span> entry.isDirectory() ? entry.getName().equals(<span class="string">"BOOT-INF/classes/"</span>) : entry.getName().startsWith(<span class="string">"BOOT-INF/lib/"</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title">main</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        (<span class="keyword">new</span> JarLauncher()).launch(args);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">launch</span><span class="params">(String[] args)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        JarFile.registerUrlProtocolHandler();</span><br><span class="line">        ClassLoader classLoader = <span class="keyword">this</span>.createClassLoader(<span class="keyword">this</span>.getClassPathArchives());</span><br><span class="line">        <span class="keyword">this</span>.launch(args, <span class="keyword">this</span>.getMainClass(), classLoader);</span><br><span class="line">&#125;</span><br><span class="line">---</span><br><span class="line"><span class="function"><span class="keyword">protected</span> <span class="keyword">void</span> <span class="title">launch</span><span class="params">(String[] args, String mainClass, ClassLoader classLoader)</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        Thread.currentThread().setContextClassLoader(classLoader);</span><br><span class="line">        <span class="keyword">this</span>.createMainMethodRunner(mainClass, args, classLoader).run();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">---</span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">MainMethodRunner</span> </span>&#123;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> String mainClassName;</span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">final</span> String[] args;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">MainMethodRunner</span><span class="params">(String mainClass, String[] args)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">this</span>.mainClassName = mainClass;</span><br><span class="line">        <span class="keyword">this</span>.args = args != <span class="keyword">null</span> ? (String[])args.clone() : <span class="keyword">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">run</span><span class="params">()</span> <span class="keyword">throws</span> Exception </span>&#123;</span><br><span class="line">        Class&lt;?&gt; mainClass = Thread.currentThread().getContextClassLoader().loadClass(<span class="keyword">this</span>.mainClassName);</span><br><span class="line">        Method mainMethod = mainClass.getDeclaredMethod(<span class="string">"main"</span>, String[].class);</span><br><span class="line">        mainMethod.invoke((Object)<span class="keyword">null</span>, <span class="keyword">this</span>.args);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>自定义的LaunchedURLClassLoader会先在本地缓存中查询是否有类，如果没有的话，就需要遍历lib下的所有jar包，寻找要加载的Class。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">package</span> org.springframework.boot.loader;</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="class"><span class="keyword">class</span> <span class="title">LaunchedURLClassLoader</span> <span class="keyword">extends</span> <span class="title">URLClassLoader</span> </span>&#123;</span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="title">LaunchedURLClassLoader</span><span class="params">(URL[] urls, ClassLoader parent)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">super</span>(urls, parent);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> URL <span class="title">findResource</span><span class="params">(String name)</span> </span>&#123;</span><br><span class="line">        Handler.setUseFastConnectionExceptions(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">        URL var2;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            var2 = <span class="keyword">super</span>.findResource(name);</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            Handler.setUseFastConnectionExceptions(<span class="keyword">false</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> var2;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> Enumeration&lt;URL&gt; <span class="title">findResources</span><span class="params">(String name)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        Handler.setUseFastConnectionExceptions(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">        LaunchedURLClassLoader.UseFastConnectionExceptionsEnumeration var2;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            var2 = <span class="keyword">new</span> LaunchedURLClassLoader.UseFastConnectionExceptionsEnumeration(<span class="keyword">super</span>.findResources(name));</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            Handler.setUseFastConnectionExceptions(<span class="keyword">false</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> var2;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">protected</span> Class&lt;?&gt; loadClass(String name, <span class="keyword">boolean</span> resolve) <span class="keyword">throws</span> ClassNotFoundException &#123;</span><br><span class="line">        Handler.setUseFastConnectionExceptions(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">        Class var3;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                <span class="keyword">this</span>.definePackageIfNecessary(name);</span><br><span class="line">            &#125; <span class="keyword">catch</span> (IllegalArgumentException var7) &#123;</span><br><span class="line">                <span class="keyword">if</span> (<span class="keyword">this</span>.getPackage(name) == <span class="keyword">null</span>) &#123;</span><br><span class="line">                    <span class="keyword">throw</span> <span class="keyword">new</span> AssertionError(<span class="string">"Package "</span> + name + <span class="string">" has already been defined but it could not be found"</span>);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            var3 = <span class="keyword">super</span>.loadClass(name, resolve);</span><br><span class="line">        &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">            Handler.setUseFastConnectionExceptions(<span class="keyword">false</span>);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">return</span> var3;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">definePackageIfNecessary</span><span class="params">(String className)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">int</span> lastDot = className.lastIndexOf(<span class="number">46</span>);</span><br><span class="line">        <span class="keyword">if</span> (lastDot &gt;= <span class="number">0</span>) &#123;</span><br><span class="line">            String packageName = className.substring(<span class="number">0</span>, lastDot);</span><br><span class="line">            <span class="keyword">if</span> (<span class="keyword">this</span>.getPackage(packageName) == <span class="keyword">null</span>) &#123;</span><br><span class="line">                <span class="keyword">try</span> &#123;</span><br><span class="line">                    <span class="keyword">this</span>.definePackage(className, packageName);</span><br><span class="line">                &#125; <span class="keyword">catch</span> (IllegalArgumentException var5) &#123;</span><br><span class="line">                    <span class="keyword">if</span> (<span class="keyword">this</span>.getPackage(packageName) == <span class="keyword">null</span>) &#123;</span><br><span class="line">                        <span class="keyword">throw</span> <span class="keyword">new</span> AssertionError(<span class="string">"Package "</span> + packageName + <span class="string">" has already been defined but it could not be found"</span>);</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">definePackage</span><span class="params">(String className, String packageName)</span> </span>&#123;</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            AccessController.doPrivileged(() -&gt; &#123;</span><br><span class="line">                String packageEntryName = packageName.replace(<span class="string">'.'</span>, <span class="string">'/'</span>) + <span class="string">"/"</span>;</span><br><span class="line">                String classEntryName = className.replace(<span class="string">'.'</span>, <span class="string">'/'</span>) + <span class="string">".class"</span>;</span><br><span class="line">                URL[] var5 = <span class="keyword">this</span>.getURLs();</span><br><span class="line">                <span class="keyword">int</span> var6 = var5.length;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">for</span>(<span class="keyword">int</span> var7 = <span class="number">0</span>; var7 &lt; var6; ++var7) &#123;</span><br><span class="line">                    URL url = var5[var7];</span><br><span class="line"></span><br><span class="line">                    <span class="keyword">try</span> &#123;</span><br><span class="line">                        URLConnection connection = url.openConnection();</span><br><span class="line">                        <span class="keyword">if</span> (connection <span class="keyword">instanceof</span> JarURLConnection) &#123;</span><br><span class="line">                            JarFile jarFile = ((JarURLConnection)connection).getJarFile();</span><br><span class="line">                            <span class="keyword">if</span> (jarFile.getEntry(classEntryName) != <span class="keyword">null</span> &amp;&amp; jarFile.getEntry(packageEntryName) != <span class="keyword">null</span> &amp;&amp; jarFile.getManifest() != <span class="keyword">null</span>) &#123;</span><br><span class="line">                                <span class="keyword">this</span>.definePackage(packageName, jarFile.getManifest(), url);</span><br><span class="line">                                <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">                            &#125;</span><br><span class="line">                        &#125;</span><br><span class="line">                    &#125; <span class="keyword">catch</span> (IOException var11) &#123;</span><br><span class="line">                    &#125;</span><br><span class="line">                &#125;</span><br><span class="line"></span><br><span class="line">                <span class="keyword">return</span> <span class="keyword">null</span>;</span><br><span class="line">            &#125;, AccessController.getContext());</span><br><span class="line">        &#125; <span class="keyword">catch</span> (PrivilegedActionException var4) &#123;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">clearCache</span><span class="params">()</span> </span>&#123;</span><br><span class="line">        URL[] var1 = <span class="keyword">this</span>.getURLs();</span><br><span class="line">        <span class="keyword">int</span> var2 = var1.length;</span><br><span class="line"></span><br><span class="line">        <span class="keyword">for</span>(<span class="keyword">int</span> var3 = <span class="number">0</span>; var3 &lt; var2; ++var3) &#123;</span><br><span class="line">            URL url = var1[var3];</span><br><span class="line"></span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                URLConnection connection = url.openConnection();</span><br><span class="line">                <span class="keyword">if</span> (connection <span class="keyword">instanceof</span> JarURLConnection) &#123;</span><br><span class="line">                    <span class="keyword">this</span>.clearCache(connection);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125; <span class="keyword">catch</span> (IOException var6) &#123;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">private</span> <span class="keyword">void</span> <span class="title">clearCache</span><span class="params">(URLConnection connection)</span> <span class="keyword">throws</span> IOException </span>&#123;</span><br><span class="line">        Object jarFile = ((JarURLConnection)connection).getJarFile();</span><br><span class="line">        <span class="keyword">if</span> (jarFile <span class="keyword">instanceof</span> org.springframework.boot.loader.jar.JarFile) &#123;</span><br><span class="line">            ((org.springframework.boot.loader.jar.JarFile)jarFile).clearCache();</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        ClassLoader.registerAsParallelCapable();</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="class"><span class="keyword">class</span> <span class="title">UseFastConnectionExceptionsEnumeration</span> <span class="keyword">implements</span> <span class="title">Enumeration</span>&lt;<span class="title">URL</span>&gt; </span>&#123;</span><br><span class="line">        <span class="keyword">private</span> <span class="keyword">final</span> Enumeration&lt;URL&gt; delegate;</span><br><span class="line"></span><br><span class="line">        UseFastConnectionExceptionsEnumeration(Enumeration&lt;URL&gt; delegate) &#123;</span><br><span class="line">            <span class="keyword">this</span>.delegate = delegate;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> <span class="keyword">boolean</span> <span class="title">hasMoreElements</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            Handler.setUseFastConnectionExceptions(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">            <span class="keyword">boolean</span> var1;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                var1 = <span class="keyword">this</span>.delegate.hasMoreElements();</span><br><span class="line">            &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                Handler.setUseFastConnectionExceptions(<span class="keyword">false</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">return</span> var1;</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="function"><span class="keyword">public</span> URL <span class="title">nextElement</span><span class="params">()</span> </span>&#123;</span><br><span class="line">            Handler.setUseFastConnectionExceptions(<span class="keyword">true</span>);</span><br><span class="line"></span><br><span class="line">            URL var1;</span><br><span class="line">            <span class="keyword">try</span> &#123;</span><br><span class="line">                var1 = (URL)<span class="keyword">this</span>.delegate.nextElement();</span><br><span class="line">            &#125; <span class="keyword">finally</span> &#123;</span><br><span class="line">                Handler.setUseFastConnectionExceptions(<span class="keyword">false</span>);</span><br><span class="line">            &#125;</span><br><span class="line"></span><br><span class="line">            <span class="keyword">return</span> var1;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Manifest-Version: <span class="number">1.0</span></span><br><span class="line">Main-Class: Hello</span><br></pre></td></tr></table></figure>


      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/blog/dubbo/import/" rel="next" title="dubbo导入">
                <i class="fa fa-chevron-left"></i> dubbo导入
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/blog/脑图/网络协议/" rel="prev" title="网络协议">
                网络协议 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            Table of Contents
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            Overview
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/blog/uploads/avatar.jpg" alt="arry">
            
              <p class="site-author-name" itemprop="name">arry</p>
              <p class="site-description motion-element" itemprop="description">Java源码/设计模式/个人记录</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/blog/archives/">
              
                  <span class="site-state-item-count">42</span>
                  <span class="site-state-item-name">posts</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/blog/categories/index.html">
                  <span class="site-state-item-count">11</span>
                  <span class="site-state-item-name">categories</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/blog/tags/index.html">
                  <span class="site-state-item-count">18</span>
                  <span class="site-state-item-name">tags</span>
                </a>
              </div>
            

          </nav>

          

          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#SpringBoot-Jar包启动原理"><span class="nav-number">1.</span> <span class="nav-text">SpringBoot Jar包启动原理</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#JAR的概念"><span class="nav-number">1.1.</span> <span class="nav-text">JAR的概念</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#可执行JAR包"><span class="nav-number">1.2.</span> <span class="nav-text">可执行JAR包</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#FatJar"><span class="nav-number">1.3.</span> <span class="nav-text">FatJar</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#自定义的ClassLoader"><span class="nav-number">1.4.</span> <span class="nav-text">自定义的ClassLoader</span></a></li></ol></li></ol></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">arry</span>

  
</div>


  <div class="powered-by">Powered by <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a></div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">Theme &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Muse</a> v5.1.4</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/blog/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/blog/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/blog/js/src/motion.js?v=5.1.4"></script>



  
  

  
  <script type="text/javascript" src="/blog/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/blog/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/blog/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  

  

  
  

  

  

  

</body>
</html>
